#include "../common/win32_con_io.h"
#include <stdio.h>
#include <stdlib.h>

enum { nTower = 3, maxTowerLen = 20 };
enum { bar = '*', post = '|'};
int towerLen;
int tower[nTower][maxTowerLen];
int top[nTower];

void drawTower()
{
    int i, j;
    for (i = 0; i < nTower; i ++){
        repeat(' ', towerLen - 1);
        printf("<%d>", i + 1);
        repeat(' ', towerLen);
    }
    putchar('\n');
    for (j = towerLen - 1; j >= 0; j--){
        for (i = 0; i < nTower; i++){
            repeat(' ', towerLen - tower[i][j]);
            repeat(bar, tower[i][j]);
            putchar(post);
            repeat(bar, tower[i][j]);
            repeat(' ', towerLen - tower[i][j]);
            putchar(' ');
        }
        putchar('\n');
    }
}

int movePin(int from, int to)
{
    if (top[from] == -1) return 1;
    if (top[to] == -1 || tower[from][top[from]] < tower[to][top[to]]){
        tower[to][++top[to]] = tower[from][top[from]];
        tower[from][top[from]--] = 0;
        return 0;
    }
    return 1;
}

int inorder(int a, int b, int c)
{
    return a <= b && b <= c;
}

void initTowers()
{
    top[1] = top[2] = -1;
    top[0] = towerLen - 1;

    int i;
    for (i = 0; i < towerLen; i++){
        tower[0][i] = towerLen - i;
    }
}

enum { ILLEGAL = -1, QUIT = -2, UNDO = -3 };

int askDigit()
{
    int c;
    c = readChar();
    
    if (c == 'q') return QUIT;
    if (c == 'u') return UNDO;
    if (!isdigit(c)) return ILLEGAL;

    putchar(c);
    return c - '0';
}

int askMove(int *from, int *to)
{
    printf("From which?\n> ");
    if ((*from = askDigit()) < 0)
        return *from;
    else if (!inorder(1, *from, nTower))
        return ILLEGAL;
    
    printf("\nTo which?\n> ");
    if ((*to = askDigit()) < 0)
        return *to;
    else if (!inorder(1, *to, nTower) || from == to)
        return ILLEGAL;
    return 0;
}

int main()
{
    printf("Height for each tower?\n> ");
    if (scanf("%d", &towerLen) != 1 || towerLen <= 2){
        printf("Quit\n");
        return 0;
    }
    // Initialize towers
    initTowers();

    int from, to;
    int illegal = 0;
    int step = 0;

    while (1){
        clearScreen();

        if (!illegal)
            step++;

        printf("Step %d\n", step);
        drawTower();

        if (top[1] == towerLen - 1){ // Winning condition
            printf("You win!\n");
            return 0;
        }else if (illegal){ // Last is illegal
            printf("Last motion illegal\n");
            illegal = 0;
        }

        int domove = 1;
        switch(askMove(&from, &to)){
        case QUIT:
            printf("Quit\n");
            return 0;
            break;
        case UNDO:
            step--;
            domove = 0;
            break;
        case ILLEGAL:
            illegal = 1;
            domove = 0;
            break;
        }
        if (domove) illegal = movePin(from - 1, to - 1);
    }
}
